package com.simplesoftwares.rebind;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;

import com.google.appengine.api.log.LogService.LogLevel;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.dev.shell.remoteui.RemoteMessageProto.Message.Request.ViewerRequest.AddLog.LogType;
import com.simplesoftwares.client.library.helperconstants.ColumnDatatype;
import com.simplesoftwares.rebind.annatonations.SearchCompositeAnnatonation;
import com.simplesoftwares.rebind.annatonations.SearchAnnotation;
import com.slicktechnologies.client.utility.AppConstants;



/**
 * Generates search pop up field.
 */
public class SearchPopUpGenerator extends SuperGenerator
{

	/** Contains all the annatonation attribute */
	protected Vector<SearchAnnotatnedFields>annotatedFields;
	
	
	/**
	 * Method fills annatonated field vector from annatonations.
	 * It read annatonations from two sources one from Method level annatonations and other 
	 * from class level annatonations.
	 */
	@Override
	protected void readAnnotatedFields()
	{
		annotatedFields=new Vector<SearchAnnotatnedFields>();
		//Get All the method corresponding to the entity
		ArrayList<JMethod>methodArray= new ArrayList<JMethod>();
		methodArray=this.getAllMethod(entityClaasType, methodArray);
		logger.log(logger.ERROR,"Entity Class Type is "+entityClaasType);
		//Get method level annatonations
		for(int i=0;i<methodArray.size();i++)
		{
			SearchAnnotation ano=methodArray.get(i).getAnnotation(SearchAnnotation.class);
			if(ano!=null)
			{
				SearchAnnotatnedFields  temp= new SearchAnnotatnedFields();
				temp.setColspan(ano.colspan());
				temp.setRowspan(ano.rowspan());
				temp.setDataType(ano.Datatype());
				temp.setEmbededQuerry(ano.EmbededQuerry());
				temp.setExtra(ano.extra());
				temp.setFlexFormNumber(ano.flexFormNumber());
				temp.setTitle(ano.title());
				temp.setVariableName(ano.variableName());
				
				//Set the JMethod object
				temp.setMethod(methodArray.get(i));
				annotatedFields.add(temp);
			}	
		}
		
		//Start reading class level Annatonations,the dependency it creates that every
		//attributes array  in class level annatonation must have same length 
		SearchCompositeAnnatonation anno=this.entityClaasType.getAnnotation(SearchCompositeAnnatonation.class);
	    if(anno!=null)
	    {
	    	int[]colSpans=anno.colspan();
	    	String[]datatypes=anno.Datatype();
	    	String[]embededQuerry=anno.EmbededQuerry();
	    	String[]extra=anno.extra();
	    	String[]flexFormNumber=anno.flexFormNumber();
	    	int[]rowspans=anno.rowspan();
	    	String[]titels=anno.title();
	    	String[]varNames=anno.variableName();
	    	logger.log(logger.ERROR,"Length of Class Level Annatonation is "+varNames.length);
	    	for(int i=0;i<colSpans.length;i++)
	    	{
	    		SearchAnnotatnedFields  temp= new SearchAnnotatnedFields();
				temp.setColspan(colSpans[i]);
				temp.setRowspan(rowspans[i]);
				temp.setDataType(datatypes[i]);
				//embeded querry can throw Array Out of bound exception as they are not always initalized
				if(embededQuerry!=null&&embededQuerry.length!=0)
					temp.setEmbededQuerry(embededQuerry[i]);
				logger.log(logger.ERROR,"Size of Extra "+extra.length);
				if(extra!=null&&extra.length!=0)
					temp.setExtra(extra[i]);
				temp.setFlexFormNumber(flexFormNumber[i]);
				temp.setTitle(titels[i]);
				temp.setVariableName(varNames[i]);
				
				annotatedFields.add(temp);
				logger.log(logger.ERROR,"Varname of class level annatontaion  "+varNames[i]);
				logger.log(logger.ERROR,"Datatype of class level annatontaion  "+datatypes[i]);
	    	}
	    	
	    }
	
	}

	/**
	 * Genearte the Variable declaration part.
	 */
	
	protected void generateVariableDeclaration()
	{
		  
		// Read the annotatedFields.
		for(SearchAnnotatnedFields temp:this.annotatedFields)
		{
			String columnDatatype=temp.getDataType();
			String variableName=temp.getVariableName();
			logger.log(logger.INFO, "VariableName:::"+variableName);
			//depending of the column type write appropriate variable declaration
		
			if(columnDatatype.equals(ColumnDatatype.TEXTBOX))
			   sWriter.println("public TextBox"+" "+variableName+";");
			
			if(columnDatatype.equals(ColumnDatatype.DOUBLEBOX))
				sWriter.println("public DoubleBox "+variableName+";");
			
			if(columnDatatype.equals(ColumnDatatype.INTEGERBOX))
				sWriter.println("public IntegerBox "+variableName+";");
			
			if(columnDatatype.equals(ColumnDatatype.LISTBOX))
				sWriter.println("public ListBox "+variableName+";");
			if(columnDatatype.equals(ColumnDatatype.CHECKBOX))
				sWriter.println("public CheckBox "+variableName+";");
			if(columnDatatype.equals(ColumnDatatype.DATEBOX))
				sWriter.println("public DateBox "+variableName+";");
			if(columnDatatype.equals(ColumnDatatype.SUGGESTBOX))
				sWriter.println("public SuggestBox "+variableName+";");
			if(columnDatatype.equals(ColumnDatatype.PERSONINFO))
			{
				sWriter.println("public PersonInfoComposite "+variableName+";");
				
			}
			
			if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXBRANCH))
			{
				sWriter.println("public ObjectListBox<Branch> "+variableName+";");
			}
			
			if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXTYPE))
			{
				sWriter.println("public ObjectListBox<Type> "+variableName+";");
			}
			
			if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXCONFIGCATEGORY))
			{
				sWriter.println("public ObjectListBox<ConfigCategory> "+variableName+";");
			}
			
			if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXEMPLOYEE))
			{
				sWriter.println("public ObjectListBox<Employee> "+variableName+";");
			}
			
			if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXCONFIG))
			{
				sWriter.println("public ObjectListBox<Config> "+variableName+";");
			}
			
			if(columnDatatype.equals(ColumnDatatype.COMMONSEARCHCOMPOSITE))
			{
				sWriter.println("public CommonSearchComposite "+variableName+";");
			}
			
			if(columnDatatype.equals(ColumnDatatype.DATECOMPARATOR))
			{
				sWriter.println("public DateComparator "+variableName+";");
			}
		}
		
	}
	
	/**
	 * Generate Variable initialization part.
	 */
	@Override
	protected void generateVariableInitialization()
	{
		sWriter.println("public void initWidget()");
		sWriter.println("{");
		
	
		for(SearchAnnotatnedFields temp:this.annotatedFields)
		{
			String columnDatatype=temp.getDataType();
			String variableName=temp.getVariableName();
			
			if(columnDatatype.equals(ColumnDatatype.PERSONINFO))
			{
				
				sWriter.println("MyQuerry querry=new MyQuerry();");
				sWriter.println("querry.setQuerryObject(new "+temp.getExtra()+"());");
				sWriter.println(variableName+"=new PersonInfoComposite(querry);");
		     }
			
			
			else if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXEMPLOYEE))
			{
				sWriter.println(variableName+"= new "+columnDatatype+"();");
				sWriter.println("AppUtility.makeSalesPersonListBoxLive("+variableName+");");
			}
			else if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXBRANCH))
			{
				sWriter.println(variableName+"= new "+columnDatatype+"();");  
				sWriter.println("AppUtility.makeBranchListBoxLive("+variableName+");");
			      
			}
			else if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXCONFIG))
			{
				sWriter.println(variableName+"= new "+columnDatatype+"();");    
				sWriter.println("AppUtility.MakeLiveConfig("+variableName+","+"Screen."+temp.getExtra()+");");
			}
			
			else if(columnDatatype.equals(ColumnDatatype.LISTBOX))
			{
				sWriter.println(variableName+"= new "+columnDatatype+"();");    
				sWriter.println("AppUtility.setStatusListBox("+variableName+","+"AppConstants."+temp.getExtra()+");");
			}
			
			else if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXCONFIGCATEGORY))
			{
				sWriter.println(variableName+"= new "+columnDatatype+"();");    
				sWriter.println("AppUtility.MakeLiveCategoryConfig("+variableName+","+"Screen."+temp.getExtra()+");");
			}
			
			else if(columnDatatype.equals(ColumnDatatype.OBJECTLISTBOXTYPE))
			{
				sWriter.println(variableName+"= new "+columnDatatype+"();");    
				sWriter.println("AppUtility.makeTypeListBoxLive("+variableName+","+"Screen."+temp.getExtra()+");");
			}
			
			else if(columnDatatype.equals(ColumnDatatype.DATECOMPARATOR))
			{
				
				String querryKind=temp.getExtra();
				logger.log(logger.ERROR,temp.getExtra()+"-----------");
				if(temp.embededQuerry.equals("")==true)
					sWriter.println(variableName+"= new "+columnDatatype+"(new "+querryKind+"());");
				else
				{
					String embededQuerry=temp.getEmbededQuerry();
					embededQuerry=cots+embededQuerry+cots;
					logger.log(logger.ERROR,temp.getEmbededQuerry()+"+++++++++++");
					sWriter.println(variableName+"= new "+columnDatatype+"("+embededQuerry+","+"new "+querryKind+"());");
				}
				
				
			}
			else
			{
				sWriter.println(variableName+"= new "+columnDatatype+"();");
				
			}
		}
	
		sWriter.println("}");
	}
	
	/**
	 * Generate create screen.
	 *
	 * @param context the context
	 */
	protected void generateCreateScreen()
	{
		
		//Write method opening body
		sWriter.println("public void createScreen()");
		//Writer opening curly
		sWriter.println("{");
		//Write initWidget
		sWriter.println("initWidget();");
		//Declare Builder object
		sWriter.println("FormFieldBuilder builder;");
	    // The form Field Declarartion class
		for(SearchAnnotatnedFields temp:this.annotatedFields)
				{
				String title=temp.getTitle();
				String varName=temp.getVariableName();
				
				sWriter.println("builder = new FormFieldBuilder("+cots+title+cots+","+varName+");");
				
				sWriter.println("FormField f"+varName.trim()+"= builder.setMandatory(false).setRowSpan"
						+ "("+temp.getRowspan()+").setColSpan("+temp.getColspan()+").build();");
				}
		
		Collections.sort(annotatedFields,new Comparator<SearchAnnotatnedFields>() {

			@Override
			public int compare(SearchAnnotatnedFields o1, SearchAnnotatnedFields o2) {
				int o1int=Integer.parseInt(o1.getFlexFormNumber());
				int o2int=Integer.parseInt(o2.getFlexFormNumber());
				if(o1int>o2int)
					return 1;
				else if(o2int>o1int)
					return -1;
			
					return 0;
			}
		});
		logger.log(logger.ERROR, "Size of Anntonated Field"+annotatedFields.size());
		
		
		
		///////////////////////////////////////UI CREATION CODE////////////////////////////////////////////		
		//Get first annatonated field flex form number
		
		//Get the row number 
		String flexStr=this.annotatedFields.get(0).getFlexFormNumber();
		int rowNumber=Integer.parseInt(flexStr.substring(0,1));
	
		//Initalize
		sWriter.println("this.fields=new FormField[][]{"
				);
		String rowItem="";
		
		for(SearchAnnotatnedFields sanno:this.annotatedFields)
		{
			flexStr=sanno.getFlexFormNumber();
			
			//Get the row number inside loop
			int temp=Integer.parseInt(flexStr.substring(0,1));
			//if row number is same start making row item
			if(rowNumber==temp)
			{
				
				rowItem=rowItem+"f"+sanno.getVariableName()+",";
				logger.log(logger.ERROR, "Row Number is "+rowNumber);
				logger.log(logger.ERROR, "Row Item is "+rowItem);
			}
			
			//Row changed now time to complete row
			else{
				//remove last comma
				rowItem = rowItem.substring(0,rowItem.length()-1);
				sWriter.println("{"+rowItem+"}"+",");
				logger.log(logger.ERROR, "Else Row Item is "+rowItem);
				rowItem="";
				rowItem=rowItem+"f"+sanno.getVariableName()+",";
				//update row number
				flexStr=sanno.getFlexFormNumber();
				rowNumber=Integer.parseInt(flexStr.substring(0,1));
				
				logger.log(logger.ERROR, "Else NEW Row Item is "+rowItem);
				}
			
		}
		
		
		//Add the last row
		rowItem = rowItem.substring(0,rowItem.length());
		sWriter.println("{"+rowItem+"}");
		
		sWriter.println("};");
		sWriter.println("}");
	}
	
	/**
	 * Generate get querry.
	 * To Do Weak Portion
	 *
	 * @param context the context
	 */
	protected void generateGetQuerry()
	{
		//Create the body of method
		//sWriter.println("@Override");
		sWriter.println("public MyQuerry getQuerry()");
		sWriter.println("{");
		sWriter.println("Vector<Filter> filtervec=new Vector<Filter>();");
		sWriter.println("Filter temp=null;");
		String entityName=entityClaasType.getSimpleSourceName();
		//Get variable name
		String variableName = null;
		String datatype = null;
		String methodName = null;
		
		
		for(SearchAnnotatnedFields temp:this.annotatedFields)
			{
				variableName=temp.getVariableName();
				datatype=temp.getDataType();
				String fieldName=null;
				if(temp.getMethod()!=null)
				{
				methodName=temp.getMethod().getName();
				methodName=methodName.replace("get", "");
				//Create the Field Name from Method Name
				fieldName=methodName.charAt(0)+"";
				fieldName=fieldName.toLowerCase();
				fieldName=fieldName+methodName.substring(1,methodName.length());
				}
					
				if(datatype.equals(ColumnDatatype.TEXTBOX))
				  {	
					  sWriter.println("if("+variableName+".getValue().trim().equals("+cots+cots+")==false){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setStringValue("+variableName+".getValue().trim());");  
					  sWriter.println("filtervec.add(temp);");
					 
					
				  }
				  
				  else if(datatype.contains("ObjectListBox"))
				  {
					  sWriter.println("if("+variableName+".getSelectedIndex()!=0){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setStringValue("+variableName+".getValue().trim());");
					 
				  }
				  else if( datatype.equals(ColumnDatatype.LISTBOX))
				  {
					  sWriter.println("if("+variableName+".getSelectedIndex()!=0){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setStringValue("+variableName+".getItemText(lbStatus.getSelectedIndex()).trim());");
					 
				  }
				
				  else if(datatype.equals(ColumnDatatype.PERSONINFO))  
				  {
					   if(temp.getMethod()!=null)
					   {
					  	 sWriter.println("if("+variableName+".getValue()!=null)");
						 sWriter.println("{");
						 sWriter.println("PersonInfo person="+variableName+".getValue();");
						 sWriter.println("temp=new Filter();");
						 logger.log(logger.ERROR,"PPPPPPPPPPP");
						 sWriter.println("temp.setIntValue(person.getCount());");
						 sWriter.println("temp.setQuerryString("+cots+fieldName+".id"+cots+");");
						 sWriter.println("filtervec.add(temp);");
						 
						 sWriter.println("temp=new Filter();");
						 sWriter.println("temp.setStringValue(person.getFullName());");
						 sWriter.println("temp.setQuerryString("+cots+fieldName+".fullName"+cots+");");
						 sWriter.println("filtervec.add(temp);");
						 
						 sWriter.println("temp=new Filter();");
						 sWriter.println("temp.setLongValue(person.getCellNumber());");
						 sWriter.println("temp.setQuerryString("+cots+fieldName+".cellNumber"+cots+");");
						 sWriter.println("filtervec.add(temp);");
						 sWriter.println("}");
					   }
					   else
					   {
						   	 sWriter.println("if("+variableName+".getValue()!=null)");
							 sWriter.println("{");
							 sWriter.println("PersonInfo person="+variableName+".getValue();");
							 sWriter.println("temp=new Filter();");
							 sWriter.println("temp.setIntValue(person.getCount());");
							 sWriter.println("temp.setQuerryString("+cots+"count"+cots+");");
							 sWriter.println("filtervec.add(temp);");
							 
							 sWriter.print("temp=new Filter();");
							 sWriter.print("temp.setStringValue(person.getFullName());");
							 sWriter.println("temp.setQuerryString("+cots+"fullname"+cots+");");
							 sWriter.println("filtervec.add(temp);");
							 
							 sWriter.print("temp=new Filter();");
							 sWriter.print("temp.setLongValue(person.getCellNumber());");
							 sWriter.println("temp.setQuerryString("+cots+"contacts.cellNo1"+cots+");");
							 sWriter.println("filtervec.add(temp);");
							 sWriter.println("}");
					   }
				  }
				
				  else if(datatype.equals(ColumnDatatype.COMMONSEARCHCOMPOSITE))
				  {
					     sWriter.println("if("+variableName+".getValue()!=null)");
					     sWriter.println("{");
						 sWriter.println("filtervec.addAll("+variableName+".getValue());");
						 sWriter.println("}");
						 
				  }
		
				  else if(datatype.equals(ColumnDatatype.INTEGERBOX))
				  {

					  sWriter.println("if("+variableName+".getValue()!=null){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setIntValue("+variableName+".getValue());"); 
					
				  }
				
				  else if(datatype.equals(ColumnDatatype.CHECKBOX))
				  {

					  sWriter.println("if("+variableName+".getValue()!=null){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setBooleanvalue("+variableName+".getValue());"); 
					
				  }
				  
				  else if(datatype.equals(ColumnDatatype.DOUBLEBOX))
				  {
					  sWriter.println("if("+variableName+".getValue()!=null){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setDoubleValue("+variableName+".getValue());"); 
					
				  }
				  
				  else if(datatype.equals(ColumnDatatype.LONGBOX))
				  {
					  sWriter.println("if("+variableName+".getValue()!=null){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setLongValue("+variableName+".getValue());"); 
					 
				  }
				  
				  else if (datatype.equals(ColumnDatatype.DATEBOX))
				  {
					  sWriter.println("if("+variableName+".getValue()!=null){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setDateValue("+variableName+".getValue());"); 
					
				  }
				  
				  else if (datatype.equals(ColumnDatatype.SUGGESTBOX))
				  {
					  sWriter.println("if("+variableName+".getValue().trim().equals("+cots+cots+")==false){");
					  sWriter.print("temp=new Filter();");
					  sWriter.println("temp.setStringValue("+variableName+".getValue().trim());"); 
					 
				  }
				
				  else if (datatype.equals(ColumnDatatype.DATECOMPARATOR))
				  {
					  sWriter.println("if("+variableName+".getValue()!=null)");
					  sWriter.println("{");
					  sWriter.println("filtervec.addAll("+variableName+".getValue());");
					  sWriter.println("}");
					 
				  }
				if(!(datatype.equals(ColumnDatatype.PERSONINFO)||datatype.equals(ColumnDatatype.DATECOMPARATOR)))
				{
			      
				 //Set querry String for normal fields
				 if((temp.getEmbededQuerry().trim().equals("")))
				    sWriter.println("temp.setQuerryString("+cots+fieldName+cots+");");
				else
					{
					String emededQuerryString=temp.getEmbededQuerry();
					sWriter.println("temp.setQuerryString("+cots+emededQuerryString+cots+");");
					}
				
				 sWriter.println("filtervec.add(temp);");
				 
				 
				 sWriter.println("}");
					
				}
			}
		
		sWriter.println("MyQuerry querry= new MyQuerry();");
		sWriter.println("querry.setFilters(filtervec);");
		sWriter.println("querry.setQuerryObject(new "+entityName+"());");
		
		sWriter.println("return querry;");
		sWriter.println("}");
	}

	@Override
	protected void generateclassBody() 
	{
		generateCreateScreen();
		generateGetQuerry();
		
	}
	
	
   


	@Override
	protected void generateImports() {
		imports=new ArrayList<String>();
		imports.add("com.google.gwt.user.client.ui.IntegerBox");
		imports.add("com.google.gwt.user.client.ui.SuggestBox");
		imports.add("com.google.gwt.user.client.ui.TextBox");
		imports.add("com.simplesoftwares.client.library.appstructure.search.MyQuerry");
		imports.add("com.simplesoftwares.client.library.appstructure.search.Filter");
		imports.add("com.simplesoftwares.client.library.FormField");
		imports.add("com.simplesoftwares.client.library.FormField");
		imports.add("com.simplesoftwares.client.library.FormFieldBuilder");
		imports.add("com.simplesoftwares.client.library.appstructure.SuperTable");
		imports.add("java.util.Vector");
		imports.add("com.google.gwt.user.client.ui.ListBox");
		imports.add("com.google.gwt.user.datepicker.client.DateBox");
		imports.add("com.simplesoftwares.client.library.mywidgets.ObjectListBox");
		imports.add("com.slicktechnologies.shared.*");
		imports.add("com.slicktechnologies.shared.common.*");
		imports.add("com.slicktechnologies.shared.common.businessprocesslayer.*");
		imports.add("com.slicktechnologies.shared.common.businessunitlayer.*");
		imports.add("com.slicktechnologies.shared.common.helperlayer.*");
		imports.add("com.slicktechnologies.shared.common.personlayer.*");
		imports.add("com.slicktechnologies.shared.common.productlayer.*");
		imports.add(entityClaasType.getQualifiedSourceName());
		imports.add(replasableClassType.getQualifiedSourceName());
		imports.add("com.simplesoftwares.client.library.composite.CommonSearchComposite");
		imports.add("com.simplesoftwares.client.library.composite.CommonSearchComposite");
		imports.add("com.simplesoftwares.client.library.composite.PersonInfoComposite");
	    imports.add("com.simplesoftwares.client.library.composite.DateComparator");
	    imports.add("com.slicktechnologies.client.utility.AppUtility");	
	    imports.add("com.google.gwt.user.client.ui.CheckBox");
	    imports.add("com.slicktechnologies.client.utility.Screen");
	    imports.add("com.slicktechnologies.client.utility.AppConstants");
	   
	}
	
	protected void generategetVarRef()
	{
		sWriter.println("public Object getVarRef(String varName)");
		sWriter.println("{");
		for(SearchAnnotatnedFields anno:this.annotatedFields)
		{
			sWriter.println("if(varName.equals("+cots+anno.getVariableName()+cots+"))");
			    sWriter.println("return this."+anno.getVariableName()+";");
		}
		sWriter.println(" return null ;");
		
		sWriter.println("}");
	}
	@Override
	protected void generateDeConstructor(String className)
	{
		sWriter.println("public "+className+"()");
		sWriter.println("{");
		sWriter.println("super();");
		sWriter.println("createGui();");
		sWriter.println("}");
		
	}


}
	
	
	
	


	
	
	
	
	

